home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb / sprite / RCS / ptraceSun.c,v < prev    next >
Encoding:
Text File  |  1991-07-03  |  9.9 KB  |  364 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     91.07.02.22.58.47;  author jhh;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  * ptrace.c --
  27.  *
  28.  *    Routines for creating a Unix like debugger interface to Sprite.
  29.  *
  30.  * Copyright 1988 Regents of the University of California
  31.  * Permission to use, copy, modify, and distribute this
  32.  * software and its documentation for any purpose and without
  33.  * fee is hereby granted, provided that the above copyright
  34.  * notice appear in all copies.  The University of California
  35.  * makes no representations about the suitability of this
  36.  * software for any purpose.  It is provided "as is" without
  37.  * express or implied warranty.
  38.  *
  39.  * $Header: /sprite/src/kernel/mach/spur.md/RCS/machConfig.c,v 1.2 88/11/11 15:3
  40. 6:43 mendel Exp $ SPRITE (Berkeley)
  41.  */
  42.  
  43. #include <stdio.h> 
  44. #include "sprite.h"
  45. #include "status.h"
  46. #include <sys/types.h>
  47. #include "sys/ptrace.h"
  48. #include <errno.h>
  49. #include <proc.h>
  50. #include <signal.h>
  51. #include <sys/wait.h>
  52. #include "procDebugRegs.h"
  53.  
  54. static int mapStatusToErrno();
  55.  
  56. /* 
  57.  *----------------------------------------------------------------------
  58.  *
  59.  * ptrace --
  60.  *
  61.  *    Emulate Unix ptrace system call.
  62.  *
  63.  * Results:
  64.  *    An integer.
  65.  *
  66.  * Side effects:
  67.  *
  68.  *----------------------------------------------------------------------
  69.  */
  70.  
  71. int
  72. ptrace (request,pid,addr,data, addr2)
  73.      enum ptracereq request;    /* Data
  74.      int pid;            /* Process id of debugee. */
  75.      char *addr;        
  76.      int data;
  77.      char *addr2;
  78. {
  79.      extern int    errno;
  80.      Proc_DebugState process_state;
  81.      int    returnData;
  82.      ReturnStatus    status;
  83.  
  84.      errno = 0;
  85.      switch (request) {
  86.         case PTRACE_TRACEME: {      /* 0, by tracee to begin tracing */
  87.          extern int    _execDebug;
  88.          /*
  89.           * This is a hack to emulate the ptrace(0) request.  ptrace(0) 
  90.           * seems to cause the exec() to stop after the first instruction.
  91.           * Setting _execDebug to true causes the Proc_Exec call to
  92.           * enter the debug queue after the first instruction.
  93.           */
  94.           _execDebug = 1;
  95.           return 0;
  96.     }
  97.         case PTRACE_PEEKTEXT:    /* 1, read word from text segment */
  98.         case PTRACE_PEEKDATA:  { /* 2, read word from data segment */
  99.         status = Proc_Debug(pid,PROC_READ, sizeof(int),addr,&returnData);
  100.         errno = mapStatusToErrno(status);
  101.         return errno ? -1 : returnData; 
  102.         }
  103.         case PTRACE_POKETEXT:    /* 4, write word into text segment */
  104.         case PTRACE_POKEDATA: {  /* 5, write word into data segment */
  105.         status = Proc_Debug(pid,PROC_WRITE, sizeof(int),&data,addr);
  106.  
  107.         if (status != 0) {
  108.         fprintf(stderr,
  109.             "Proc_Debug failed status = %x, pid = %x, addr = %x\n",
  110.             status, pid, addr);
  111.         }
  112.  
  113.         errno = mapStatusToErrno(status);
  114.         return errno ? -1 : data; 
  115.         }
  116.         case PTRACE_CONT: {       /* 7, continue process */
  117.         if (data != 0 && data != 1) {
  118.         if (kill(pid,data) != 0) {
  119.             perror("kill");
  120.             return -1;
  121.         }
  122.         }
  123.         status = Proc_Debug(pid,PROC_CONTINUE,0,0,0);
  124.         errno = mapStatusToErrno(status);
  125.         return errno ? -1 : 0; 
  126.         }
  127.         case PTRACE_KILL: {      /* 8, terminate process */
  128.         if (kill(pid,SIGKILL) != 0) {
  129.         perror("kill");
  130.         return -1;
  131.         }
  132.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  133.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  134.                        * one kill.
  135.                        */
  136.         (void) kill(pid,SIGCONT); 
  137.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  138.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  139.                        * one kill.
  140.                        */
  141.         (void) kill(pid,SIGCONT); 
  142.         (void) kill(pid,SIGKILL); /* Sometimes Sprite takes more than
  143.                        * one kill.
  144.                        */
  145.         status= Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  146.         if (status == PROC_INVALID_PID) {
  147.         status = SUCCESS;
  148.         }
  149.         errno = mapStatusToErrno(status);
  150.         return errno ? -1 : 0; 
  151.     }
  152.         case PTRACE_SINGLESTEP:{ /* 9, single step process */
  153.         status = Proc_Debug(pid,PROC_SINGLE_STEP,0,0,0);
  154.         errno = mapStatusToErrno(status);
  155.         return errno ? -1 : 0; 
  156.         }
  157.         case PTRACE_ATTACH: {  /* 10, attach to an existing process */
  158.         status = Proc_Debug(pid,PROC_GET_THIS_DEBUG,0,0,0);
  159.         errno = mapStatusToErrno(status);
  160.         return errno ? -1 : 0; 
  161.     }
  162.         case PTRACE_DETACH: {  /* 11, detach from a process */
  163.         if (data != 0 && data != 1) {
  164.         if (kill(pid,data) != 0) {
  165.             perror("kill");
  166.             return -1;
  167.         }
  168.         }
  169.         status = Proc_Debug(pid,PROC_DETACH_DEBUGGER,0,0,0);
  170.         errno = mapStatusToErrno(status);
  171.         return errno ? -1 : 0; 
  172.     }
  173.        case PTRACE_GETREGS: {     /* 12, get all registers */
  174.         status = Proc_Debug(pid,PROC_GET_DBG_STATE,0,0,&process_state);
  175.         errno = mapStatusToErrno(status);
  176.         procDebugToPtraceRegs(&process_state.regState, addr);
  177.         return errno ? -1 : 0; 
  178.     }
  179.        case PTRACE_SETREGS: {     /* 13, set all registers */
  180.         status = Proc_Debug(pid,PROC_GET_DBG_STATE,0,0,&process_state);
  181.         ptraceToProcDebugRegs(addr, &process_state.regState);
  182.         status = Proc_Debug(pid,PROC_SET_DBG_STATE,0,&process_state,0);
  183.         errno = mapStatusToErrno(status);
  184.         return errno ? -1 : 0; 
  185.     }
  186.  
  187.         case PTRACE_READTEXT:   /* 18, read text segment */
  188.         case PTRACE_READDATA: { /* 16, read data segment */
  189.         status = Proc_Debug(pid,PROC_READ, (int) data,addr,addr2);
  190.         errno = mapStatusToErrno(status);
  191.         return errno ? -1 : 0; 
  192.         }
  193.         case PTRACE_WRITEDATA:   /* 17, write data segment */
  194.         case PTRACE_WRITETEXT: {  /* 19 write data into data segment */
  195.         status = Proc_Debug(pid,PROC_WRITE, (int)data,addr2,addr);
  196.         errno = mapStatusToErrno(status);
  197.         return errno ? -1 : data; 
  198.         }
  199.        case PTRACE_GETFPREGS: {  /* 14, get all floating point regs */
  200.         return 0;
  201.        }
  202.        case PTRACE_SETFPREGS: { /* 15, set all floating point regs */
  203.         return 0;
  204.        }
  205.        case PTRACE_PEEKUSER:    /* 3, read word from user struct */
  206.        case PTRACE_POKEUSER:    /* 6, write word into user struct */
  207.        default: {
  208.         return -1;
  209.     }
  210.     }
  211. }
  212.  
  213. /* 
  214.  *----------------------------------------------------------------------
  215.  *
  216.  * wait --
  217.  *
  218.  *    Emulate the Unix wait system call when used to wait for a 
  219.  *    process being ptraced.
  220.  *
  221.  * Results:
  222.  *    An integer.
  223.  *
  224.  * Side effects:
  225.  *
  226.  *----------------------------------------------------------------------
  227.  */
  228. int
  229. wait (statusPtr)
  230.     union wait *statusPtr;
  231. {
  232.     ReturnStatus    status;
  233.     Proc_DebugState process_state;
  234.     extern int inferior_pid;
  235.  
  236.     if (!inferior_pid) {
  237.     error("Trying to wait for nonexistant process");
  238.     }
  239.     /*
  240.      * Wait for this process to enter the debug list.
  241.      */
  242.     status = Proc_Debug(inferior_pid,PROC_GET_THIS_DEBUG,0,0,0);
  243.     if (status == SUCCESS) {
  244.     if (statusPtr == (union wait *) 0) {
  245.         goto reapChild;
  246.         return inferior_pid;
  247.     }
  248.     status = Proc_Debug(inferior_pid,PROC_GET_DBG_STATE,0,0,&process_state);
  249.     if (status == SUCCESS) {
  250.         int unixSignal;
  251.             statusPtr->w_status = 0;
  252.             statusPtr->w_stopval = WSTOPPED;
  253.             if (process_state.termReason == PROC_TERM_SUSPENDED) {
  254.                 (void)Compat_SpriteSignalToUnix(process_state.termStatus,
  255.                            &unixSignal);
  256.                 statusPtr->w_stopsig = unixSignal;
  257.         if (process_state.termStatus == SIG_DEBUG ||
  258.             process_state.termStatus == SIG_TRACE_TRAP ||
  259.             process_state.termStatus == SIG_BREAKPOINT) {
  260.             statusPtr->w_stopsig = SIGTRAP;
  261.         }
  262.             } else if (process_state.termReason == PROC_TERM_SIGNALED ||
  263.                        process_state.termReason == PROC_TERM_RESUMED) {
  264.                 (void)Compat_SpriteSignalToUnix(process_state.termStatus, 
  265.                         &unixSignal);
  266.                 statusPtr->w_stopsig = unixSignal;
  267.         if (process_state.termStatus == SIG_DEBUG ||
  268.             process_state.termStatus == SIG_TRACE_TRAP ||
  269.             process_state.termStatus == SIG_BREAKPOINT) {
  270.             statusPtr->w_stopsig = SIGTRAP;
  271.         }
  272.             } else {
  273.         statusPtr->w_status = 0;
  274.                 statusPtr->w_retcode = process_state.termStatus;
  275.         (void) ptrace(PTRACE_DETACH,inferior_pid,0,SIGKILL,0);
  276.             }
  277.         return inferior_pid;
  278.     }
  279.     }
  280. reapChild:
  281.     { 
  282.         Proc_PID    pid;
  283.     int        reason, childStatus, subStatus;
  284.     status = Proc_Wait(1, (int *) &inferior_pid, PROC_WAIT_BLOCK, 
  285.         &pid, &reason,  &childStatus, &subStatus, 
  286.         (Proc_ResUsage *) NULL);
  287.         if (statusPtr != NULL)  {
  288.         int        unixSignal;
  289.             statusPtr->w_status = 0;
  290.             if (reason == PROC_TERM_SUSPENDED) {
  291.                 (void)Compat_SpriteSignalToUnix(childStatus, &unixSignal);
  292.                 statusPtr->w_stopval = WSTOPPED;
  293.                 statusPtr->w_stopsig = unixSignal;
  294.             } else if (reason == PROC_TERM_SIGNALED ||
  295.                        reason == PROC_TERM_RESUMED) {
  296.                 (void)Compat_SpriteSignalToUnix(childStatus, &unixSignal);
  297.                 statusPtr->w_stopval = WSTOPPED;
  298.                 statusPtr->w_termsig = unixSignal;
  299.             } else {
  300.                 statusPtr->w_retcode = childStatus;
  301.         (void) ptrace(PTRACE_DETACH,inferior_pid,0,SIGKILL,0);
  302.             }
  303.         }
  304.     }
  305.     return inferior_pid;
  306. }
  307.  
  308.  
  309.  
  310.  
  311. /* 
  312.  *----------------------------------------------------------------------
  313.  *
  314.  * mapStatusToErrno --
  315.  *
  316.  *    Map a Sprite status return code to a Unix errno. This is intended 
  317.  *    to work only on the status codes returns from Proc_Debug.
  318.  *
  319.  * Results:
  320.  *    An integer.
  321.  *
  322.  * Side effects:
  323.  *      None
  324.  *
  325.  *----------------------------------------------------------------------
  326.  */
  327.  
  328. static int
  329. mapStatusToErrno(status)
  330.     ReturnStatus    status;
  331. {
  332.     int    returnValue;
  333.  
  334.     if (status == SUCCESS) {
  335.     return 0;
  336.     }
  337.  
  338.     switch (status) {
  339.  
  340.     case PROC_INVALID_PID:
  341.     returnValue = ESRCH;
  342.     break;
  343.  
  344.     case SYS_INVALID_ARG:
  345.     returnValue = EINVAL;
  346.     break;
  347.  
  348.     case SYS_ARG_NOACCESS:
  349.     returnValue = EINVAL;
  350.     break;
  351.  
  352.     case GEN_ABORTED_BY_SIGNAL:
  353.     returnValue = EINTR;
  354.     break;
  355.  
  356.     default:
  357.     returnValue = EIO;
  358.     break;
  359.     }
  360.     return returnValue;
  361. }
  362.  
  363. @
  364.